home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cmln0285.arc / ARGPAR.H < prev    next >
Text File  |  1986-02-27  |  41KB  |  1,318 lines

  1.  
  2.  
  3.                             ARGPAR.H
  4.                        by Alexander Abacus
  5.                        February 1985 issue
  6.  
  7.  
  8. /* argparse.h: @(#) macros for parsing command arguments. */
  9. /* by Alexander B. Abacus */
  10. /* Computer Language BBS file name: ARGPAR.H */
  11. /* This file is formatted for readability and may not be used with */
  12. /* all C compilers.  For more portable version see ARGPARSE.H */
  13.  
  14. #if defined Hargparse
  15.    /* #endfile                  -- this file already included */
  16. #else ! defined Hargparse       /* first inclusion */
  17. #  define Hargparse             /* and really include this file */
  18.  
  19. #  ifdef COMMENT
  20.    /*
  21.    /* Macros defined in this file can be used to parse command line
  22.    /* as it is passed to the main program.  Macro MAIN
  23.    /* can be used to produce the header of the function "main()".
  24.    /* Other macros should be used within the body of the function
  25.    /* main(). Macros ArgBEGIN(), ArgLOOP, and ArgEND must be used to
  26.    /* sandwich in the other macros.
  27.    /*
  28.    /* Command arguments can be positional or key letter arguments.
  29.    /* Key letter arguments start with a trigger character. Any
  30.    /* character can be specified as trigger character.
  31.    /* The default trigger character is '-'.
  32.    /*
  33.    /* Key letter arguments can be defined as either flag or text
  34.    /* arguments.
  35.    /*
  36.    /* Flag argument consists of a single key letter that
  37.    /* follows the trigger character. No text is expected after the
  38.    /* flag key letter. If any text follows a flag key letter without
  39.    /* a white space it is interpreted as additional key letters.
  40.    /* If any text follows a flag key letter after a white space
  41.    /* it is interpreted as another argument. Several flag key letters
  42.    /* may follow one trigger character.
  43.    /*
  44.    /* Text argument consists of a single key letter immediately
  45.    /* following a trigger character and followed by text either
  46.    /* immediately or after a white space.
  47.    /*
  48.    /* Positional arguments can be processed either after all
  49.    /* key letter arguments have been processed, or all arguments
  50.    /* can be processed in order, intermixing positional arguments
  51.    /* with key arguments. Double trigger character can be used
  52.    /* to signal the end of key letter arguments.  Another mode
  53.    /* is provided, but not recommended, in which the first
  54.    /* positional argument terminates key letter arguments.
  55.    /*
  56.    /*
  57.    /* For both Flag and Text arguments two macros exist:
  58.    /* one that Sets a variable and another that Calls a user
  59.    /* defined function.
  60.    /*
  61.    /* Following flags are predefined and can not be redefined:
  62.    /* '?'  Output tutorial information to stderr.
  63.    /* '!'  Output debugging information to stderr.
  64.    /* '-'  (i.e. trigger character) end of key letter arguments.
  65.    /*
  66.    /*
  67.    /* Macros:
  68.    /*
  69.    /* @(#) ArgTutor( ... ) -- used internally.
  70.    /*   Print tutorial message from string array 'tutorial'
  71.    /*   to stderr and exit abnormally.
  72.    /*
  73.    /* @(#) MAIN()
  74.    /*   Defines header for function main(argc, argv, envp).
  75.    /*
  76.    /* @(#) ArgMAIN is same as ArgBEGIN(argc, argv)
  77.    /*
  78.    /* @(#) ArgBEGIN( ArgumentCountVariable, ArgumentVector )
  79.    /*   Begins sandwich that parses command arguments.
  80.    /*   Macros described before ArgLOOP are optional.
  81.    /*   If present, they must be coded between ArgBEGIN
  82.    /*   and ArgLOOP.  Those macros override provided defaults.
  83.    /*   Each of them should be coded only once, if at all.
  84.    /*   Macros described between ArgLOOP and ArgEND should
  85.    /*   also be coded between ArgLOOP and ArgEND.
  86.    /*   One of those macros must be coded for each key letter
  87.    /*   argument.
  88.    /*
  89.    /* @(#) ArgTrigger( TriggerCharacter )
  90.    /*   TriggerCharacter is used to recognize key letter arguments.
  91.    /*   Default is '-'.
  92.    /*
  93.    /* @(#) ArgDescription( DescriptionStringArray )
  94.    /*   Provides text to be printed after an error is detected
  95.    /*   while parsing arguments.
  96.    /*      char * tutorial[] = { 'Command', 'summary', 0 };
  97.    /*
  98.    /* @(#) ArgKeyLeading
  99.    /*   If this macro is coded key arguments must precede positional
  100.    /*   arguments.  After the first positional argument is recognized,
  101.    /*   all following arguments are treated as positional.
  102.    /*   This mode is not recommended.  It is provided just for the
  103.    /*   sake of completeness (many programs parse arguments this way).
  104.    /*
  105.    /* @(#) ArgPosCall( FunctionName )
  106.    /*   FunctionName is called for each positional argument.
  107.    /*   If positional arguments are to be processed after all
  108.    /*   key letter arguments, this macro should be left out.
  109.    /*   It defaults to the dummy function "argPos()"
  110.    /*   defined in this file. Otherwise a function
  111.    /*   should be defined as:
  112.    /*     char * functionName( keyCharacter, textString )
  113.    /*     char   keyCharacter;  /* Always contains '\0'. */
  114.    /*     char * textString;    /* Points to positional argument. */
  115.    /*     { ... }
  116.    /*
  117.    /* @(#) ArgMin( MinPositionals )
  118.    /*   MinPositionals is minimum number of positional arguments.
  119.    /*   If this macro is not coded, the check is not performed.
  120.    /*
  121.    /* @(#) ArgMax( MaxPositionals )
  122.    /*   MaxPositionals is maximum number of positional arguments.
  123.    /*   If this macro is not coded, the check is not performed.
  124.    /*
  125.    /* @(#) ArgLOOP
  126.    /*   This macro marks the end of default override macros.
  127.    /*   It is followed by macros describing key letter arguments.
  128.    /*
  129.    /* @(#) ArgFlagSet( KeyLetter, CounterVariable )
  130.    /*   Increment counter for this flag.
  131.    /*   CounterVariable should be initially zero.
  132.    /*
  133.    /* @(#) ArgTextSet( KeyLetter, PointerVariable )
  134.    /*   Set pointer to text argument.
  135.    /*
  136.    /* @(#) ArgFlagCall( KeyLetter, FunctionName )
  137.    /* @(#) ArgTextCall( KeyLetter, FunctionName )
  138.    /*   Call user defined function to process key letter argument.
  139.    /*   Function must be defined as:
  140.    /*     char * functionName( keyCharacter, textString )
  141.    /*     char   keyCharacter;  /* Key letter. */
  142.    /*     char * textString;    /* NULL for flag, or points to text. */
  143.    /*     { ... }
  144.    /*   If pointer returned by this function is not NULL,
  145.    /*   the tutorial message will be printed to stderr
  146.    /*   and abnormal exit will be taken.
  147.    /*
  148.    /* @(#) ArgEND
  149.    /*   Ends sandwich that parses command arguments.
  150.    /*
  151.    /* Example of use: See end of this file.
  152.    */
  153. #  endif COMMENT
  154.  
  155. /*[ A.1 ] Include for debugging. */
  156.  
  157. #  if ! defined FILE
  158. #    include <stdio.h>
  159. #  endif ! defined FILE
  160.  
  161. #  if ! defined Hdebug
  162. #    include "debug.h"
  163. #  endif ! defined Hdebug
  164.  
  165. /*[ A.2 ] Output tutorial information. */
  166.  
  167. #  define ArgTutor(A_Tutorial) \
  168.      { \
  169.        char ** line; \
  170.        for ( (line = A_Tutorial); ((*line) != (char *) 0); (++line) ) \
  171.        { \
  172.          StdMsg \
  173.          ( stderr \
  174.          , " %s" \
  175.          , *line \
  176.          ); \
  177.        } \
  178.        ABEND(1); \
  179.      } \
  180.  
  181. /*[ B.1 ] Standard heading for main(). */
  182.  
  183. #  define MAIN() \
  184.      main(argc, argv, envp) \
  185.      int argc; \
  186.      char *argv[]; \
  187.      char *envp[]; \
  188.  
  189. /*[ B.2 ] Begin sandwich, parse, process positional arguments. */
  190.  
  191. #  define ArgMAIN ArgBEGIN(argc, argv)
  192.  
  193. #  define ArgBEGIN(A_argc, A_argv) \
  194.    { /* Begin block with local variables. Ends with ArgEND. */ \
  195.      struct \
  196.      { \
  197.        int     argc; \
  198.        int *   ptrArgCount; \
  199.        char ** argVector; \
  200.        char *  (*ptrFunction) (); \
  201.        int     minPositionals; \
  202.        int     maxPositionals; \
  203.        int     keysLeading; \
  204.        char    keyTrigger; \
  205.        char ** tutorial; \
  206.        \
  207.        char *  description[2]; \
  208.        int     argIndex; \
  209.        int     charIndex; \
  210.        int     nextPositional; \
  211.        int     noOfPositionals; \
  212.        int     keysTerminated; /* ON/OFF switch */ \
  213.        char *  textPointer; \
  214.        char *  keyPointer; \
  215.      } a0; \
  216.      \
  217.      a0.ptrArgCount = &(A_argc); \
  218.      a0.argc = *a0.ptrArgCount; \
  219.      a0.argVector = (A_argv); \
  220.      a0.minPositionals = -1; \
  221.      a0.maxPositionals = -1; \
  222.      a0.ptrFunction = argPos; \
  223.      a0.keysLeading = 0; \
  224.      a0.keyTrigger = '-'; \
  225.      a0.tutorial = & a0.description[0]; \
  226.      a0.description[0] = "Description of arguments is not provided.\n"; \
  227.      a0.description[1] = (char *) 0; \
  228.  
  229. /*[ B.3 ] Optional macros to override defaults. */
  230.  
  231. #define ArgMin(A_Min)          a0.minPositionals = (A_Min);
  232. #define ArgMax(A_Max)          a0.maxPositionals = (A_Max);
  233. #define ArgPosCall(A_Function) a0.ptrFunction = (A_Function);
  234. #define ArgKeyLeading          a0.keysLeading = 1;
  235. #define ArgTrigger(A_Trigger)  a0.keyTrigger = (A_Trigger);
  236. #define ArgDescription(A_Text) a0.tutorial = (A_Text);
  237.  
  238. /*[ B.4 ] Begining of argument loop. */
  239.  
  240. #define ArgLOOP \
  241.      a0.keysTerminated = 0; \
  242.      a0.nextPositional = 1; \
  243.      a0.argIndex = 1; \
  244.      \
  245.      if ( ( a0.argVector[1][0] == a0.keyTrigger ) \
  246.      &&   ( a0.argVector[1][1] == '!'           ) ) \
  247.      { \
  248.        a0.textPointer = & a0.argVector[1][1]; \
  249.        DEBUGIN \
  250.        ( \
  251.          /* if not followed by characters, debug all levels */ \
  252.          if ( (* (a0.textPointer + 1)) == '\0' ) debug[0] = (char) 127; \
  253.          \
  254.          /* if followed by characters, select debugging levels */ \
  255.          while ( (* ++a0.textPointer) != '\0' ) \
  256.          { /* for all characters following -! */ \
  257.            if ((* a0.textPointer) < 128) ++debug[* a0.textPointer]; \
  258.          } /* for all characters following -! */ \
  259.        ) /* DEBUGIN */ \
  260.        DEBUGOUT \
  261.        ( \
  262.          StdMsg \
  263.          ( stderr \
  264.          , " Compiled without debugging code. Option -! ineffective.\n" \
  265.          ); \
  266.        ) /* DEBUGOUT */ \
  267.        ++a0.argIndex; \
  268.      } \
  269.      \
  270.      for ( (a0.argIndex); (a0.argIndex < a0.argc); (++a0.argIndex) ) \
  271.      { /* for all arguments */ \
  272.        if ( ( a0.argVector[a0.argIndex][0] != a0.keyTrigger ) \
  273.        ||   ( a0.keysTerminated != 0                        ) \
  274.        ||   ( a0.argVector[a0.argIndex][1] == '\0'          ) ) \
  275.        { /* not a key: bubble up positional arguments */ \
  276.          DEBUG \
  277.          ( 3, \
  278.            StdMsg \
  279.            ( stderr \
  280.            , "Positional argument %d \"%s\".\n" \
  281.            , a0.nextPositional \
  282.            , a0.argVector[a0.argIndex] \
  283.            ); \
  284.          ) /* DEBUG */ \
  285.          if \
  286.          (  ( a0.maxPositionals  >= 0 ) \
  287.          && ( a0.nextPositional > a0.maxPositionals ) \
  288.          ) \
  289.          { /* if(too many positionals) */ \
  290.            StdMsg \
  291.            ( stderr \
  292.            , " Stop. Maximum %d positional arguments, excess at \"%s\".\n" \
  293.            , a0.maxPositionals \
  294.            , a0.argVector[a0.argIndex] \
  295.            ); \
  296.            ArgTutor( a0.tutorial ); \
  297.          } /* if(too many positionals) */ \
  298.          a0.keysTerminated |= a0.keysLeading; \
  299.          a0.argVector[a0.nextPositional] = a0.argVector[a0.argIndex]; \
  300.          (void) (*a0.ptrFunction) ( '\0', a0.argVector[a0.nextPositional] ); \
  301.          ++a0.nextPositional; \
  302.        } \
  303.        else /* it is a key */ \
  304.        { \
  305.          DEBUG \
  306.          ( 3, \
  307.            StdMsg \
  308.            ( stderr \
  309.            , "Key argument \"%s\".\n" \
  310.            , a0.argVector[a0.argIndex] \
  311.            ); \
  312.          ) /* DEBUG */ \
  313.          a0.charIndex = 0; \
  314.          a0.keyPointer = & a0.argVector[a0.argIndex][0]; \
  315.          do \
  316.          { /* for all characters in an argument */ \
  317.            ++a0.charIndex; \
  318.            ++a0.keyPointer; \
  319.            DEBUG \
  320.            ( 3, \
  321.              StdMsg \
  322.              ( stderr \
  323.              , "Key letter \'%c\'.\n" \
  324.              , *a0.keyPointer \
  325.              ); \
  326.            ) /* DEBUG */ \
  327.            if ( a0.keyPointer[0] == a0.keyTrigger ) \
  328.            { \
  329.              if ( a0.charIndex != 1 ) \
  330.              { \
  331.                StdMsg \
  332.                ( stderr \
  333.                , " Stop. Terminator of keys must be alone: \"%s\".\n" \
  334.                , a0.argVector[a0.argIndex] \
  335.                ); \
  336.                ArgTutor( a0.tutorial ); \
  337.              } \
  338.              if ( a0.keyPointer[1] != '\0' ) \
  339.              { \
  340.                StdMsg \
  341.                ( stderr \
  342.                , " Stop. Terminator of keys followed by: \"%s\".\n" \
  343.                , a0.argVector[a0.argIndex] \
  344.                ); \
  345.                ArgTutor( a0.tutorial ); \
  346.              } \
  347.              a0.keysTerminated = 1; \
  348.            } \
  349.            else \
  350.            { \
  351.              switch ( a0.keyPointer[0] ) \
  352.              { \
  353.              case '?': \
  354.                ArgTutor( a0.tutorial ); \
  355.                EXIT( a0.argc != 2); \
  356.  
  357. #  ifdef COMMENT
  358.    /*
  359.    /* The previous and the following macro form the sandwich into which
  360.    /* macro calls defining key letter arguments will be inserted.
  361.    /* Comunication between macros making up the sandwich is through
  362.    /* the members of the structure declared in the previous macro.
  363.    /* The structure is local to the sandwich.
  364.    */
  365. #  endif COMMENT
  366.  
  367. /*[ B.5 ] End sandwich, verify number of positional arguments. */
  368.  
  369. #   define ArgEND \
  370.              default: \
  371.                StdMsg \
  372.                ( stderr \
  373.                , " Stop. Key letter \'%c\' rejected.\n" \
  374.                , *a0.keyPointer \
  375.                ); \
  376.                ArgTutor( a0.tutorial ); \
  377.                break; \
  378.              } /* switch */ \
  379.            } /* if not double trigger */ \
  380.          } /* for all characters in argument */ \
  381.          while ( a0.keyPointer != (char *) 0 ); \
  382.        } /* if key or not a key */ \
  383.      } /* for all arguments */ \
  384.      \
  385.      a0.noOfPositionals = a0.nextPositional - 1; \
  386.      \
  387.      if \
  388.      (  ( a0.minPositionals  >= 0 ) \
  389.      && ( a0.noOfPositionals < a0.minPositionals ) \
  390.      ) \
  391.      { /* if(too few positionals) */ \
  392.        StdMsg \
  393.        ( stderr \
  394.        , " Stop. Minimum %d positional arguments, %d supplied.\n" \
  395.        , a0.minPositionals \
  396.        , a0.noOfPositionals \
  397.        ); \
  398.        ArgTutor( a0.tutorial ); \
  399.      } /* if(too few positionals) */ \
  400.      \
  401.      (* a0.ptrArgCount) = a0.noOfPositionals; \
  402.    } /* End block begun with ArgBEGIN. */ \
  403.  
  404. /*[ C.1 ] Key-letter flag argument, deferred processing. */
  405.  
  406. #  define ArgFlagSet(A_KeyLetter, A_FlagCounter) \
  407.      case A_KeyLetter: \
  408.        ++A_FlagCounter; \
  409.        DEBUG \
  410.        ( 3, \
  411.          StdMsg \
  412.          ( stderr \
  413.          , "Flag \'%c\' accepted, occurance number %d.\n" \
  414.          , *a0.keyPointer \
  415.          , A_FlagCounter \
  416.          ); \
  417.        ) /* DEBUG */ \
  418.        break; \
  419.  
  420. /*[ C.2 ] Key-letter flag argument, immediate processing. */
  421.  
  422. #  define ArgFlagCall(A_KeyLetter, A_FlagFunction) \
  423.      case A_KeyLetter: \
  424.        DEBUG \
  425.        ( 3, \
  426.          StdMsg \
  427.          ( stderr \
  428.          , "Flag \'%c\' accepted, function \"%s()\" called.\n" \
  429.          , *a0.keyPointer \
  430.          , "A_FlagFunction" \
  431.          ); \
  432.        ) /* DEBUG */ \
  433.        if (A_FlagFunction ( *a0.keyPointer, (char *) 0 ) != (char *) 0 ) \
  434.        { \
  435.          ArgTutor( a0.tutorial ); \
  436.        } \
  437.        break; \
  438.  
  439. /*[ C.3 ] Key-letter text argument, deferred processing. */
  440.  
  441. #  define ArgTextSet(A_KeyLetter, A_TextPointer) \
  442.      case A_KeyLetter: \
  443.        if ( A_TextPointer != (char *) 0 ) \
  444.        { \
  445.          StdMsg \
  446.          ( stderr \
  447.          , " Stop. Repeated key-letter '%c' with text.\n" \
  448.          , A_KeyLetter \
  449.          ); \
  450.          ArgTutor( a0.tutorial ); \
  451.        } \
  452.        argText \
  453.        ( & A_TextPointer \
  454.        , & a0.keyPointer \
  455.        , & a0.argIndex \
  456.        ,   a0.charIndex \
  457.        ,   a0.keyTrigger \
  458.        ,   a0.argc \
  459.        ,   a0.argVector \
  460.        ,   a0.tutorial \
  461.        ); \
  462.        break; \
  463.  
  464. /*[ C.4 ] Key-letter text argument, immediate processing. */
  465.  
  466. #  define ArgTextCall(A_KeyLetter, A_TextFunction) \
  467.      case A_KeyLetter: \
  468.        argText \
  469.        ( & a0.textPointer \
  470.        , & a0.keyPointer \
  471.        , & a0.argIndex \
  472.        ,   a0.charIndex \
  473.        ,   a0.keyTrigger \
  474.        ,   a0.argc \
  475.        ,   a0.argVector \
  476.        ,   a0.tutorial \
  477.        ); \
  478.        if(A_TextFunction ( A_KeyLetter, a0.textPointer ) != (char *) 0 ) \
  479.        { \
  480.          ArgTutor( a0.tutorial ); \
  481.        } \
  482.        break; \
  483.  
  484. /*[ D.1 ] Dummy function for processing positional arguments. */
  485.  
  486. static
  487. char * argPos( a_keyChar, a_argString )
  488. char   a_keyChar;
  489. char * a_argString;
  490. {
  491.   START  ( '0', "argPos", 0 )
  492.   RETURN ( (char) 0 );
  493. }
  494.  
  495. /*[ D.2 ] Function common for key-letter text arguments. */
  496.  
  497. static Void argText
  498. (       a_textPointer
  499. ,           a_keyPointer
  500. ,               a_argIndex
  501. ,                   a_charIndex
  502. ,                       a_keyTrigger
  503. ,                           a_argc
  504. ,                               a_argv
  505. ,                                   a_tutorial
  506. )
  507. char ** a_textPointer;
  508. char **     a_keyPointer;
  509. int *           a_argIndex;
  510. int                 a_charIndex;
  511. char                    a_keyTrigger;
  512. int                         a_argc;
  513. char *                          a_argv[];
  514. char *                              a_tutorial[];
  515. { /* argText() */
  516.   START('0', "argText", "(string) \"%s\"")
  517.  
  518.   if ( a_charIndex != 1 )
  519.   {
  520.     StdMsg
  521.     ( stderr
  522.     , " Stop. Key letter with text must stand alone: \"%s\".\n"
  523.     , a_argv[*a_argIndex]
  524.     );
  525.     ArgTutor( & a_tutorial[0] );
  526.   }
  527.   else if ( ( (*a_keyPointer)[1]) != '\0' )
  528.   { /* text following key letter without a separating white space */
  529.     (*a_textPointer) = (char *) & (*a_keyPointer)[1];
  530.   }
  531.   else /* text must be in the following argument */
  532.   {
  533.     ++(*a_argIndex);
  534.     if ( ((*a_argIndex) >= a_argc)
  535.     ||   (a_keyTrigger == *a_argv[*a_argIndex]) )
  536.     { /* text is missing */
  537.       StdMsg
  538.       ( stderr
  539.       , " Stop. Text not found after key letter \"%s\".\n"
  540.       , *a_keyPointer
  541.       );
  542.       --(*a_argIndex);
  543.       ArgTutor( & a_tutorial[0] );
  544.     }
  545.     else
  546.     {
  547.       (*a_textPointer) = (char *) a_argv[*a_argIndex];
  548.     } /* endif */
  549.   } /* endif */
  550.  
  551.   DEBUG
  552.   ( 3,
  553.     StdMsg
  554.     ( stderr
  555.     , "Key letter \'%c\' with text \"%s\".\n"
  556.     , ** a_keyPointer
  557.     , *  a_textPointer
  558.     );
  559.   ) /* DEBUG */
  560.  
  561.   (*a_keyPointer) = (char *) 0;
  562.   RETURN ( Nothing );
  563. } /* argText() */
  564.  
  565. /* --------------------------------------------------------------- */
  566.  
  567. #  if defined DriverH
  568. #  undef DriverH
  569.  
  570. /* T.1: Test driver for this include. */
  571.  
  572. #define Storage static
  573. #include "debug.h"
  574.  
  575. static char * tutorial[] =
  576. {
  577. "Expected arguments are: file1 file2 \n",
  578. "   file1 is the source, \n",
  579. "   file2 is the target. \n",
  580. 0
  581. };
  582.  
  583. main(argCount, argVector)
  584. int    argCount;
  585. char * argVector[];
  586. {
  587.   int    f_flag = 0;
  588.   char  *t_text = (char *) 0;
  589.   START('m', "main", 0)
  590.  
  591.   ArgBEGIN      (argCount, argVector)
  592.   ArgMin        (1)
  593.   ArgMax        (2)
  594.   ArgDescription(tutorial)
  595.   ArgLOOP
  596.   ArgFlagSet  ('f', f_flag)
  597.   ArgTextSet  ('t', t_text)
  598.   ArgFlagCall ('F', argPos)
  599.   ArgTextCall ('T', argPos)
  600.   ArgEND
  601.  
  602.   EXIT (0);
  603. } /* main */
  604.  
  605. #  endif DriverH
  606.  
  607. #endif Hargparse
  608.  
  609. /* argparse.h: End of file. */
  610.  
  611. *********************************************************************
  612.  
  613.  
  614.                     Other files of importance
  615.                        by Alexander Abacus
  616.  
  617.  
  618.                            ARGBEGIN.H
  619.  
  620.  
  621. /* argbegin.h: @(#) Begin argument parsing sandwich, see argparse.h */
  622. /* by Alexander B. Abacus */
  623.  
  624. #ifndef ArgCount
  625. #define ArgCount argc
  626. #endif
  627.  
  628. #ifndef ArgVector
  629. #define ArgVector argv
  630. #endif
  631.  
  632. { /* Begin block with local variables. Ends with argend.h */
  633.   struct
  634.   {
  635.     char ** tutorial;
  636.     char ** argVector;
  637.     char *  description[2];
  638.     char *  textPointer;
  639.     char *  keyPointer;
  640.     char *  (*ptrFunction) ();
  641.     int *   ptrArgCount;
  642.     int     argc;
  643.     int     minPositionals;
  644.     int     maxPositionals;
  645.     int     keysLeading;
  646.     int     argIndex;
  647.     int     charIndex;
  648.     int     nextPositional;
  649.     int     noOfPositionals;
  650.     int     keysTerminated; /* ON/OFF switch */
  651.     char    keyTrigger;
  652.   } a0;
  653.  
  654.   a0.ptrArgCount = &(ArgCount);
  655.   a0.argc = *a0.ptrArgCount;
  656.   a0.argVector = (ArgVector);
  657.   a0.minPositionals = -1;
  658.   a0.maxPositionals = -1;
  659.   a0.ptrFunction = argPos;
  660.   a0.keysLeading = 0;
  661.   a0.keyTrigger = '-';
  662.   a0.tutorial = & a0.description[0];
  663.   a0.description[0] = "Description of arguments is not provided.\n";
  664.   a0.description[1] = (char *) 0;
  665.  
  666. /* argbegin.h: End of file. */
  667.  
  668.  
  669.                             ARGEND.H
  670.  
  671. /* argend.h: @(#) End sandwichbegun with argbegin.h, see argparse.h */
  672. /* by Alexander B. Abacus */
  673.  
  674.           default:
  675.             fprintf
  676.             ( stderr
  677.             , " Stop. Key letter \'%c\' rejected.\n"
  678.             , *a0.keyPointer
  679.             );
  680.             ArgTutor( a0.tutorial );
  681.             break;
  682.           } /* switch */
  683.         } /* if not double trigger */
  684.       } /* for all characters in argument */
  685.       while ( a0.keyPointer != (char *) 0 );
  686.     } /* if key or not a key */
  687.   } /* for all arguments */
  688.  
  689.   a0.noOfPositionals = a0.nextPositional - 1;
  690.  
  691.   if
  692.   (  ( a0.minPositionals  >= 0 )
  693.   && ( a0.noOfPositionals < a0.minPositionals )
  694.   )
  695.   { /* if(too few positionals) */
  696.     fprintf
  697.     ( stderr
  698.     , " Stop. Minimum %d positional arguments, %d supplied.\n"
  699.     , a0.minPositionals
  700.     , a0.noOfPositionals
  701.     );
  702.     ArgTutor( a0.tutorial );
  703.   } /* if(too few positionals) */
  704.  
  705.   (* a0.ptrArgCount) = a0.noOfPositionals;
  706. } /* End block begun with argbegin.h */
  707.  
  708. /* argend.h: End of file. */
  709.  
  710.  
  711.                             ARGLOOP.H
  712.  
  713. /* argloop.h: @(#) Begining of argument loop, see argparse.h */
  714. /* by Alexander B. Abacus */
  715.  
  716.   a0.keysTerminated = 0;
  717.   a0.nextPositional = 1;
  718.   a0.argIndex = 1;
  719.  
  720.   if ( ( a0.argVector[1][0] == a0.keyTrigger )
  721.   &&   ( a0.argVector[1][1] == '!'           ) )
  722.   {
  723.     a0.textPointer = & a0.argVector[1][1];
  724. #ifdef Debug
  725.       /* if not followed by characters, debug all levels */
  726.       if ( (* (a0.textPointer + 1)) == '\0' ) debug[0] = (char) 127;
  727.  
  728.       /* if followed by characters, select debugging levels */
  729.       while ( (* ++a0.textPointer) != '\0' )
  730.       { /* for all characters following -! */
  731.         if ((* a0.textPointer) < 128) ++debug[* a0.textPointer];
  732.       } /* for all characters following -! */
  733. #else ! defined Debug
  734.       fprintf
  735.       ( stderr
  736.       , " Compiled without debugging code. Option -! ineffective.\n"
  737.       );
  738. #endif Debug
  739.     ++a0.argIndex;
  740.   }
  741.  
  742.   for ( (a0.argIndex); (a0.argIndex < a0.argc); (++a0.argIndex) )
  743.   { /* for all arguments */
  744. #ifdef DriverH
  745.     fprintf ( stderr, "Word %d \"%s\".\n", a0.argIndex, a0.argVector[a0.argIndex] );
  746. #endif DriverH
  747.  
  748.     if ( ( a0.argVector[a0.argIndex][0] != a0.keyTrigger )
  749.     ||   ( a0.keysTerminated != 0                        )
  750.     ||   ( a0.argVector[a0.argIndex][1] == '\0'          ) )
  751.     { /* not a key: bubble up positional arguments */
  752.       if
  753.       (  ( a0.maxPositionals  >= 0 )
  754.       && ( a0.nextPositional > a0.maxPositionals )
  755.       )
  756.       { /* if(too many positionals) */
  757.         fprintf
  758.         ( stderr
  759.         , " Stop. Maximum %d positional arguments, excess at \"%s\".\n"
  760.         , a0.maxPositionals
  761.         , a0.argVector[a0.argIndex]
  762.         );
  763.         ArgTutor( a0.tutorial );
  764.       } /* if(too many positionals) */
  765.       a0.keysTerminated |= a0.keysLeading;
  766.       a0.argVector[a0.nextPositional] = a0.argVector[a0.argIndex];
  767.       /* (void) */ (*a0.ptrFunction) ( '\0', a0.argVector[a0.nextPositional] );
  768.       ++a0.nextPositional;
  769.     }
  770.     else /* it is a key */
  771.     {
  772.       a0.charIndex = 0;
  773.       a0.keyPointer = & a0.argVector[a0.argIndex][0];
  774.       do
  775.       { /* for all characters in an argument */
  776.         ++a0.charIndex;
  777.         ++a0.keyPointer;
  778.         if ( (*a0.keyPointer) == '\0' ) { break; } /* from do ... while */
  779. #ifdef DriverH
  780.         fprintf( stderr, "Remaining argument: \"%s\".\n", a0.keyPointer );
  781. #endif DriverH
  782.  
  783.         if ( a0.keyPointer[0] == a0.keyTrigger )
  784.         {
  785.           if ( a0.charIndex != 1 )
  786.           {
  787.             fprintf
  788.             ( stderr
  789.             , " Stop. Terminator of keys must be alone: \"%s\".\n"
  790.             , a0.argVector[a0.argIndex]
  791.             );
  792.             ArgTutor( a0.tutorial );
  793.           }
  794.           if ( a0.keyPointer[1] != '\0' )
  795.           {
  796.             fprintf
  797.             ( stderr
  798.             , " Stop. Terminator of keys followed by: \"%s\".\n"
  799.             , a0.argVector[a0.argIndex]
  800.             );
  801.             ArgTutor( a0.tutorial );
  802.           }
  803.           a0.keysTerminated = 1;
  804.         }
  805.         else
  806.         {
  807.           switch ( a0.keyPointer[0] )
  808.           {
  809.           case '?':
  810.             ArgTutor( a0.tutorial );
  811.             exit( a0.argc != 2);
  812.  
  813. /* argloop.h: End of file. */
  814.  
  815.  
  816.                             ARGPAR.1
  817.  
  818.  
  819.  
  820.                             Listing 1
  821.                                to
  822.                 Macros Special Series on C Macros
  823.                           February 1985
  824.  
  825.  
  826.      >> Simplified argument parsing, positional and flag <<
  827.  
  828.  
  829.  
  830. #define ArgBEGIN(A_argc, A_argv) \
  831.    { /* Begin block with local variables. Ends with ArgEND. */ \
  832.      struct \
  833.      { int     argc, *ptrArgCount; \
  834.        char ** argVector; \
  835.        char *  (*ptrFunction) (); \
  836.        char    keyTrigger, *keyPointer; \
  837.        int     argIndex, charIndex, nextPositional, keysTerminated; \
  838.      } a0; \
  839.      a0.ptrArgCount = &(A_argc); a0.argVector = (A_argv); \
  840.      a0.argc = *a0.ptrArgCount; a0.keyTrigger = '-'; \
  841.      a0.ptrFunction = argPos;
  842.  
  843. #define ArgPosCall(A_Function) a0.ptrFunction = (A_Function);
  844. #define ArgTrigger(A_Trigger)  a0.keyTrigger = (A_Trigger);
  845.  
  846. #define ArgLOOP \
  847.      a0.keysTerminated = 0; a0.nextPositional = 1; \
  848.      for ( (a0.argIndex = 1); (a0.argIndex < a0.argc); (++a0.argIndex) ) \
  849.      { /* for all arguments */ \
  850.        if ( ( a0.argVector[a0.argIndex][0] != a0.keyTrigger ) \
  851.        ||   ( a0.keysTerminated != 0                        ) \
  852.        ||   ( a0.argVector[a0.argIndex][1] == '\0'          ) ) \
  853.        { /* not a key: bubble up positional arguments */ \
  854.          a0.argVector[a0.nextPositional] = a0.argVector[a0.argIndex]; \
  855.          (void) (*a0.ptrFunction) ( '\0', a0.argVector[a0.nextPositional] ); \
  856.          ++a0.nextPositional; \
  857.        } \
  858.        else /* it is a key */ \
  859.        { \
  860.          for \
  861.          ( (a0.charIndex = 1, a0.keyPointer = & a0.argVector[a0.argIndex][1]) \
  862.          ; (  (   a0.keyPointer  != (char *) 0 ) \
  863.            && ( (*a0.keyPointer) != '\0' ) \
  864.            ) \
  865.          ; (++a0.charIndex, ++a0.keyPointer) \
  866.          ) \
  867.          { /* for all characters in an argument */ \
  868.            switch ( a0.keyPointer[0] ) \
  869.            {
  870.  
  871. #define ArgFlagSet(A_KeyLetter, A_FlagCounter) \
  872.            case A_KeyLetter: ++A_FlagCounter; break;
  873.  
  874. #define ArgFlagCall(A_KeyLetter, A_Function) \
  875.            case A_KeyLetter: (A_Function)( *a0.keyPointer, 0 ); break;
  876.  
  877. #define ArgEND \
  878.            default: \
  879.              (void) fprintf \è             ( stderr \
  880.              , " Stop. Key letter \'%c\' rejected.\n" \
  881.              , *a0.keyPointer \
  882.              ); \
  883.              exit (1); \
  884.            } /* switch */ \
  885.          } /* for all characters in argument */ \
  886.        } /* if key or not a key */ \
  887.      } /* for all arguments */ \
  888.      (* a0.ptrArgCount) = a0.nextPositional - 1; \
  889.    } /* End block begun with ArgBEGIN. */ \
  890.  
  891. static char * argPos( a_keyChar, a_argString )
  892. char   a_keyChar, *a_argString;
  893. { return ( (char *) 0 ); }
  894.  
  895. /* --------------------------------------------------------------- */
  896.  
  897. #if defined DriverH
  898.  
  899. #include <stdio.h>
  900.  
  901. void main(argCount, argVector)
  902. int    argCount;
  903. char * argVector[];
  904. {
  905.   int    f_flag = 0;
  906.  
  907.   ArgBEGIN    (argCount, argVector)
  908.   ArgPosCall  (argPos)
  909.   ArgTrigger  ('-')
  910.   ArgLOOP
  911.   ArgFlagSet  ('f', f_flag)
  912.   ArgFlagCall ('F', argPos)
  913.   ArgEND
  914.  
  915.   exit (0);
  916. } /* main */
  917.  
  918. #endif DriverH
  919.  
  920.  
  921.                            ARGPARSE.H
  922.  
  923. /* argparse.h: @(#) macros for parsing command arguments. */
  924. /* by Alexander B. Abacus */
  925. /* Computer Language BBS file name ARGPARSE.H */
  926. /* This and related files make a more portable version of ARGPAR.H */
  927. /* related files: argparse.use, argbegin.h, argloop.h, argend.h */
  928.  
  929. #ifdef Hargsmall
  930.    /* #endfile                  -- this file already included */
  931. #else ! defined Hargparse       /* first inclusion */
  932.  
  933. #define Hargsmall
  934.                                 /* and really include this file */
  935. /*[ A.1 ] Required include. */
  936.  
  937. #ifndef FILE
  938. #include <stdio.h>
  939. #endif ! defined FILE
  940.  
  941. /*[ A.2 ] Output tutorial information. */
  942.  
  943. /* void */ ArgTutor(line)
  944. char ** line;
  945. {
  946.   for ( (line); ((*line) != (char *) 0); (++line) )
  947.   {
  948.     fprintf
  949.     ( stderr
  950.     , " %s"
  951.     , *line
  952.     );
  953.   }
  954.   exit(1);
  955. }
  956.  
  957. /*[ A.3 ] Dummy function for processing positional arguments. */
  958.  
  959. static
  960. char * argPos( a_keyChar, a_argString )
  961. char   a_keyChar;
  962. char * a_argString;
  963. {
  964. #ifdef DriverH
  965.   fprintf ( stderr, "Argument" );
  966.   if ( a_keyChar != '\0' )
  967.   {
  968.     fprintf ( stderr, " key-letter \'%c\'", a_keyChar );
  969.   }
  970.   if ( a_argString != (char *) 0 )
  971.   {
  972.     fprintf ( stderr, " text \"%s\"", a_argString );
  973.   }
  974.   fprintf ( stderr, ".\n" );
  975. #endif DriverH
  976.   return ( (char *) 0 );
  977. }
  978.  
  979. /*[ B.1 ] Standard heading for main(). */
  980.  
  981. #define MAIN() main(argc, argv, envp) int argc; char *argv[]; char *envp[];
  982.  
  983. /*[ B.2 ] Optional macros to override defaults. */
  984.  
  985. #define ArgMin(A_Min)          a0.minPositionals = (A_Min);
  986. #define ArgMax(A_Max)          a0.maxPositionals = (A_Max);
  987. #define ArgPosCall(A_Function) a0.ptrFunction = (A_Function);
  988. #define ArgKeyLeading          a0.keysLeading = 1;
  989. #define ArgTrigger(A_Trigger)  a0.keyTrigger = (A_Trigger);
  990. #define ArgDescription(A_Text) a0.tutorial = (A_Text);
  991.  
  992. /*[ C.1 ] Key-letter flag argument, deferred processing. */
  993.  
  994. #define ArgFlagSet(A_KeyLetter, A_FlagCounter) case A_KeyLetter: ++A_FlagCounter; break;
  995.  
  996. /*[ C.2 ] Key-letter flag argument, immediate processing. */
  997.  
  998. #define ArgFlagCall(A_KeyLetter, A_FlagFunction) case A_KeyLetter: if (A_FlagFunction ( *a0.keyPointer, (char *) 0 ) != (char *) 0 ) { ArgTutor( a0.tutorial ); } break;
  999.  
  1000.  
  1001. /*[ C.3 ] Key-letter text argument, deferred processing. */
  1002.  
  1003. #define ArgTextSet(A_KeyLetter, A_TextPointer) \
  1004.      case A_KeyLetter: \
  1005.        argText \
  1006.        ( & A_TextPointer \
  1007.        , & a0.keyPointer \
  1008.        , & a0.argIndex \
  1009.        ,   a0.charIndex \
  1010.        ,   a0.keyTrigger \
  1011.        ,   a0.argc \
  1012.        ,   a0.argVector \
  1013.        ,   a0.tutorial \
  1014.        ,   A_KeyLetter \
  1015.        ,   0 \
  1016.        ); \
  1017.        break;
  1018.  
  1019. /*[ C.4 ] Key-letter text argument, immediate processing. */
  1020.  
  1021. #define ArgTextCall(A_KeyLetter, A_TextFunction) \
  1022.      case A_KeyLetter: \
  1023.        argText \
  1024.        ( & a0.textPointer \
  1025.        , & a0.keyPointer \
  1026.        , & a0.argIndex \
  1027.        ,   a0.charIndex \
  1028.        ,   a0.keyTrigger \
  1029.        ,   a0.argc \
  1030.        ,   a0.argVector \
  1031.        ,   a0.tutorial \
  1032.        ,   A_KeyLetter \
  1033.        ,   A_TextFunction \
  1034.        ); \
  1035.        break;
  1036.  
  1037. /*[ D.2 ] Function common for key-letter text arguments. */
  1038.  
  1039. static /* void */ argText
  1040. (       a_textPointer
  1041. ,           a_keyPointer
  1042. ,               a_argIndex
  1043. ,                   a_charIndex
  1044. ,                       a_keyTrigger
  1045. ,                           a_argc
  1046. ,                               a_argv
  1047. ,                                   a_tutorial
  1048. ,                                      a_keyLetter
  1049. ,                                          a_textFunction
  1050. )
  1051. char ** a_textPointer;
  1052. char **     a_keyPointer;
  1053. int *           a_argIndex;
  1054. int                 a_charIndex;
  1055. char                    a_keyTrigger;
  1056. int                         a_argc;
  1057. char *                          a_argv[];
  1058. char *                              a_tutorial[];
  1059. char                                   a_keyLetter;
  1060. char *                                   (*a_textFunction) ();
  1061. { /* argText() */
  1062.   if ( a_textFunction == 0 )
  1063.   { /* ArgTextSet */
  1064.     if ( (* a_textPointer) != (char *) 0 )
  1065.     { /* second occurance of this key letter */
  1066.       fprintf
  1067.       ( stderr
  1068.       , " Stop. Repeated key-letter '%c' with text.\n"
  1069.       , a_keyLetter
  1070.       );
  1071.       ArgTutor( a_tutorial );
  1072.     } /* second occurance of this key letter */
  1073.   } /* ArgTextSet */
  1074.  
  1075.   if ( a_charIndex != 1 )
  1076.   {
  1077.     fprintf
  1078.     ( stderr
  1079.     , " Stop. Key letter with text must stand alone: \"%s\".\n"
  1080.     , a_argv[*a_argIndex]
  1081.     );
  1082.     ArgTutor( & a_tutorial[0] );
  1083.   }
  1084.   else if ( ( (*a_keyPointer)[1]) != '\0' )
  1085.   { /* text following key letter without a separating white space */
  1086.     (*a_textPointer) = (char *) & (*a_keyPointer)[1];
  1087.   }
  1088.   else /* text must be in the following argument */
  1089.   {
  1090.     ++(*a_argIndex);
  1091.     if ( ((*a_argIndex) >= a_argc)
  1092.     ||   (a_keyTrigger == *a_argv[*a_argIndex]) )
  1093.     { /* text is missing */
  1094.       fprintf
  1095.       ( stderr
  1096.       , " Stop. Text not found after key letter \"%s\".\n"
  1097.       , *a_keyPointer
  1098.       );
  1099.       --(*a_argIndex);
  1100.       ArgTutor( & a_tutorial[0] );
  1101.     }
  1102.     else
  1103.     {
  1104.       (*a_textPointer) = (char *) a_argv[*a_argIndex];
  1105.     } /* endif */
  1106.   } /* endif */
  1107.  
  1108.   if ( a_textFunction != 0 )
  1109.   { /* ArgTextCall */
  1110.     if((*a_textFunction) ( a_keyLetter, (* a_textPointer) ) != (char *) 0 )
  1111.     {
  1112.       ArgTutor( a_tutorial );
  1113.     }
  1114.   } /* ArgTextCall */
  1115.  
  1116.   (*a_keyPointer) = (char *) 0;       /* to skip to next element of argv */
  1117.  
  1118.   return;
  1119. } /* argText() */
  1120.  
  1121. /* --------------------------------------------------------------- */
  1122.  
  1123. #ifdef DriverH
  1124.  
  1125. /* T.1: Test driver for this include. */
  1126.  
  1127. static char * tutorial[] =
  1128. {
  1129. "Expected arguments are: file1 file2 \n",
  1130. "   file1 is the source, \n",
  1131. "   file2 is the target. \n",
  1132. 0
  1133. };
  1134.  
  1135. main(argCount, argVector)
  1136. int    argCount;
  1137. char * argVector[];
  1138. {
  1139.   int    f_flag = 0;
  1140.   char  *t_text = (char *) 0;
  1141.  
  1142. #define ArgCount  argCount
  1143. #define ArgVector argVector
  1144. #include "argbegin.h"
  1145.   ArgMin        (1)
  1146.   ArgMax        (2)
  1147.   ArgDescription(tutorial)
  1148. #include "argloop.h"
  1149.   ArgFlagSet  ('f', f_flag)
  1150.   ArgFlagCall ('F', argPos)
  1151.   ArgTextSet  ('t', t_text)
  1152.   ArgTextCall ('T', argPos)
  1153. #include "argend.h"
  1154.  
  1155.   fprintf ( stderr, "Flag counter: %d.\n", f_flag );
  1156.   if ( t_text != (char *) 0 )
  1157.   {
  1158.     fprintf ( stderr, "Text: \"%s\".\n", t_text );
  1159.   }
  1160.  
  1161.   exit (0);
  1162. } /* main */
  1163.  
  1164. #endif DriverH
  1165.  
  1166. #endif Hargsmall
  1167.  
  1168. /* argparse.h: End of file. */
  1169.  
  1170.  
  1171.                           ARGPARSE.USE
  1172.  
  1173.  
  1174. #ifdef COMMENT
  1175. /*
  1176. /* This file describes the use of files: argparse.h, argbegin.h, argloop.h,
  1177. /* and argend.h.  Those files make a more portable implementation of the
  1178. /* macros defined and described in the file argpar.h.
  1179. /* The most important difference is that macros ArgBEGIN(), ArgLOOP, and
  1180. /* ArgEND have been replaced with include files argbegin.h, argloop.h, and
  1181. /* argend.h.  Text of those macros exceeds buffer sizes of C preprocessors
  1182. /* on micro-computers.
  1183. /*
  1184. /* Macros described in this file can be used to parse command line
  1185. /* as it is passed to the main program.  Macro MAIN
  1186. /* can be used to produce the header of the function "main()".
  1187. /* Other macros should be used within the body of the function
  1188. /* main(). Includes argbegin.h, argloop.h, and argend.h must be used to
  1189. /* sandwich in the macros.
  1190. /*
  1191. /* Command arguments can be positional or key letter arguments.
  1192. /* Key letter arguments start with a trigger character. Any
  1193. /* character can be specified as trigger character.
  1194. /* The default trigger character is '-'.
  1195. /*
  1196. /* Key letter arguments can be defined as either flag or text
  1197. /* arguments.
  1198. /*
  1199. /* Flag argument consists of a single key letter that
  1200. /* follows the trigger character. No text is expected after the
  1201. /* flag key letter. If any text follows a flag key letter without
  1202. /* a white space it is interpreted as additional key letters.
  1203. /* If any text follows a flag key letter after a white space
  1204. /* it is interpreted as another argument. Several flag key letters
  1205. /* may follow one trigger character.
  1206. /*
  1207. /* Text argument consists of a single key letter immediately
  1208. /* following a trigger character and followed by text either
  1209. /* immediately or after a white space.
  1210. /*
  1211. /* Positional arguments can be processed either after all
  1212. /* key letter arguments have been processed, or all arguments
  1213. /* can be processed in order, intermixing positional arguments
  1214. /* with key arguments. Double trigger character can be used
  1215. /* to signal the end of key letter arguments.  Another mode
  1216. /* is provided, but not recommended, in which the first
  1217. /* positional argument terminates key letter arguments.
  1218. /*
  1219. /*
  1220. /* For both Flag and Text arguments two macros exist:
  1221. /* one that Sets a variable and another that Calls a user
  1222. /* defined function.
  1223. /*
  1224. /* Following flags are predefined and can not be redefined:
  1225. /* '?'  Output tutorial information to stderr.
  1226. /* '!'  Output debugging information to stderr.
  1227. /* '-'  (i.e. trigger character) end of key letter arguments.
  1228. /*
  1229. /*
  1230. /* Macros:
  1231. /*
  1232. /* @(#) ArgTutor( ... ) -- used internally.
  1233. /*   Print tutorial message from string array 'tutorial'
  1234. /*   to stderr and exit abnormally.
  1235. /*
  1236. /* @(#) MAIN()
  1237. /*   Defines header for function main(argc, argv, envp).
  1238. /*
  1239. /* @(#) #define ArgCount  argc
  1240. /* @(#) #define ArgVector argv
  1241. /* @(#) #include 'argbegin.h'
  1242. /*   Begins sandwich that parses command arguments.
  1243. /*   Macros described before argloop.h are optional.
  1244. /*   If present, they must be coded between argbegin.h
  1245. /*   and argloop.h.  Those macros override provided defaults.
  1246. /*   Each of them should be coded only once, if at all.
  1247. /*   Macros described between argloop.h and argend.h should
  1248. /*   also be coded between argloop.h and argend.h.
  1249. /*   One of those macros must be coded for each key letter
  1250. /*   argument.
  1251. /*
  1252. /* @(#) ArgTrigger( TriggerCharacter )
  1253. /*   TriggerCharacter is used to recognize key letter arguments.
  1254. /*   Default is '-'.
  1255. /*
  1256. /* @(#) ArgDescription( DescriptionStringArray )
  1257. /*   Provides text to be printed after an error is detected
  1258. /*   while parsing arguments.
  1259. /*      char * tutorial[] = { 'Command', 'summary', 0 };
  1260. /*
  1261. /* @(#) ArgKeyLeading
  1262. /*   If this macro is coded key arguments must precede positional
  1263. /*   arguments.  After the first positional argument is recognized,
  1264. /*   all following arguments are treated as positional.
  1265. /*   This mode is not recommended.  It is provided just for the
  1266. /*   sake of completeness (many programs parse arguments this way).
  1267. /*
  1268. /* @(#) ArgPosCall( FunctionName )
  1269. /*   FunctionName is called for each positional argument.
  1270. /*   If positional arguments are to be processed after all
  1271. /*   key letter arguments, this macro should be left out.
  1272. /*   It defaults to the dummy function "argPos()"
  1273. /*   defined in this file. Otherwise a function
  1274. /*   should be defined as:
  1275. /*     char * functionName( keyCharacter, textString )
  1276. /*     char   keyCharacter;  /* Always contains '\0'. */
  1277. /*     char * textString;    /* Points to positional argument. */
  1278. /*     { ... }
  1279. /*
  1280. /* @(#) ArgMin( MinPositionals )
  1281. /*   MinPositionals is minimum number of positional arguments.
  1282. /*   If this macro is not coded, the check is not performed.
  1283. /*
  1284. /* @(#) ArgMax( MaxPositionals )
  1285. /*   MaxPositionals is maximum number of positional arguments.
  1286. /*   If this macro is not coded, the check is not performed.
  1287. /*
  1288. /* @(#) #include 'argloop.h'
  1289. /*   This macro marks the end of default override macros.
  1290. /*   It is followed by macros describing key letter arguments.
  1291. /*
  1292. /* @(#) ArgFlagSet( KeyLetter, CounterVariable )
  1293. /*   Increment counter for this flag.
  1294. /*   CounterVariable should be initially zero.
  1295. /*
  1296. /* @(#) ArgTextSet( KeyLetter, PointerVariable )
  1297. /*   Set pointer to text argument.
  1298. /*
  1299. /* @(#) ArgFlagCall( KeyLetter, FunctionName )
  1300. /* @(#) ArgTextCall( KeyLetter, FunctionName )
  1301. /*   Call user defined function to process key letter argument.
  1302. /*   Function must be defined as:
  1303. /*     char * functionName( keyCharacter, textString )
  1304. /*     char   keyCharacter;  /* Key letter. */
  1305. /*     char * textString;    /* NULL for flag, or points to text. */
  1306. /*     { ... }
  1307. /*   If pointer returned by this function is not NULL,
  1308. /*   the tutorial message will be printed to stderr
  1309. /*   and abnormal exit will be taken.
  1310. /*
  1311. /* @(#) #include 'argend.h'
  1312. /*   Ends sandwich that parses command arguments.
  1313. /*
  1314. /* Example of use: See end of file argparse.h.
  1315. */
  1316. #endif COMMENT
  1317.  
  1318.